package com.ruoyi.project.setting.security.service;

import com.dyun.tool.jwt.prop.SecureProperties;
import com.dyun.tool.jwt.utils.JWTUtil;
import com.ruoyi.project.setting.security.LoginUser;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.CustomException;
import net.dreamlu.mica.core.spring.SpringContextUtil;
import net.dreamlu.mica.core.utils.WebUtil;
import net.dreamlu.mica.launch.MicaProperties;
import net.dreamlu.mica.redis.cache.MicaRedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * token验证处理
 *
 * @author ruoyi
 */
@Component
public class TokenService {

    @Autowired
    private MicaRedisCache redisCache;

    /**
     * 获取用户身份信息（已登录）
     *
     * @return 用户信息
     */
    public LoginUser currentLoginUser() {
        // 用户身份伪造、身份过期抛出401未认证
        CustomException customException = new CustomException("身份认证失败，无法获取用户信息", HttpStatus.UNAUTHORIZED.value());
        try {
            // 解析jwt信息
            Map<String, Object> user = JWTUtil.getUser(Objects.requireNonNull(WebUtil.getRequest()));
            String uuid = (String) user.get(com.dyun.tool.jwt.constant.UserConstants.PRINCIPAL);
            // 获取用户信息
            LoginUser loginUser = redisCache.get(getTokenKey(uuid));
            if (loginUser == null) {
                throw customException;
            }
            return loginUser;
        } catch (Exception e) {
            throw customException;
        }
    }

    /**
     * 设置用户身份信息
     */
    public void setLoginUser(LoginUser loginUser) {
        if (loginUser != null && !StringUtils.isEmpty(loginUser.getToken())) {
            refreshToken(loginUser);
        }
    }

    /**
     * 刷新令牌有效期
     *
     * @param loginUser 登录信息
     */
    public void refreshToken(LoginUser loginUser) {
        loginUser.setLoginTime(System.currentTimeMillis());
        long expireTime = SpringContextUtil.getBean(SecureProperties.class).getExpireTime();
        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * 1000);
        // 根据uuid将loginUser缓存
        String userKey = getTokenKey(loginUser.getToken());
        redisCache.setEx(userKey, loginUser, expireTime);
    }

    /**
     * 删除用户身份信息
     */
    public void delLoginUser(String token) {
        if (!StringUtils.isEmpty(token)) {
            String userKey = getTokenKey(token);
            redisCache.del(userKey);
        }
    }

    /**
     * 所有在线用户
     */
    public List<Object> getOnlineUsers() {
        return redisCache.mGet(redisCache.keys(getTokenKey("*")));
    }

    private String getTokenKey(String uuid) {
        return SpringContextUtil.getBean(MicaProperties.class).getName() + ":" + 
                UserConstants.LOGIN_TOKEN_KEY + uuid;
    }
}
